home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / editor / gsar110.zip / GSAR.C < prev    next >
C/C++ Source or Header  |  1996-08-08  |  31KB  |  943 lines

  1. /* gsar.c ***************************************** updated: 960808.09:28 TT
  2.  *
  3.  * Description : General Search And Replace utility (gsar)
  4.  * Author      : Tormod Tjaberg & Hans Peter Verne
  5.  *
  6.  * Copyright (C) 1992-96 Tormod Tjaberg & Hans Peter Verne,
  7.  * This is free software, distributed under the terms of the
  8.  * GNU General Public License. For details see the file COPYING
  9.  */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include <stdarg.h>
  15. #include <limits.h>
  16. #include <signal.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include "comp_dep.h"
  20. #include "arg_func.h"
  21. #include "gsar.h"
  22.  
  23. #define PROGRAM_NAME "gsar"
  24. #define PROGRAM_VER  "1.10"
  25.  
  26. /* Need setmode to turn my streams into binary Under MS-DOS
  27.  */
  28. #ifdef MSDOS
  29. #include <fcntl.h>
  30. #include <io.h>
  31. #endif
  32.  
  33. #ifdef __UNIX__
  34. #include <unistd.h>
  35. #endif
  36.  
  37. /* Clever little option mimic wildcard expansion from
  38.  * shell ONLY available with the Zortech compiler ver 3.0x and upwards
  39.  * And in the Symantec compiler though it's been renamed
  40.  */
  41. #if defined(__ZTC__)
  42. #include <dos.h>
  43. #ifdef WILDCARDS
  44. WILDCARDS
  45. #endif
  46. #ifdef EXPAND_WILDCARDS
  47. EXPAND_WILDCARDS
  48. #endif
  49. #endif
  50.  
  51. /* Macro to determine if char is a path or drive delimiter
  52.  */
  53. #define IS_PATH_DELIM(c)   ((c) == '\\' || (c) == ':' || (c) == '/')
  54.  
  55. #define LF  0xa
  56. #define CR  0xd
  57.  
  58. #define SETVBUF_SIZ  0x4000      
  59.  
  60. unsigned short nItemsSearch = 0;
  61. unsigned short nItemsReplace = 0;
  62.  
  63. /* if the flag below is set we are not allowed to interrupt!
  64.  */
  65. #if defined(__UNIX__)
  66. /* SunOS does not have this definition, so play it safe */
  67. static int fCriticalPart = 0;
  68. #else
  69. static sig_atomic_t fCriticalPart = 0;
  70. #endif
  71.  
  72. OUTPUT_CTRL Ctrl;
  73.  
  74. char **pFileList;           /* list of files found on the command line */
  75. char *pOutFile = NULL;      /* current output file name make sure it's NULL */
  76. char  SearchBuf[PAT_BUFSIZ] = "";
  77. char  ReplaceBuf[PAT_BUFSIZ] = "";
  78.  
  79. char  fSearchReplace = 0;  /* default to a search initially */
  80. char  fFolded        = 0;  /* fold pattern ie. ignore case */
  81. char  fOverWrite     = 0;  /* overwrite input file */
  82. char  fForce         = 0;  /* force overwrite of existing output file */
  83. char  fBuffers       = 0;  /* just display search & replace buffers */
  84. char  fFilter        = 0;  /* make GSAR act like a filter */
  85.  
  86. /* Usage text and GNU licence information
  87.  */
  88. char *Usage[] =
  89. {
  90.   PROGRAM_NAME ", ver " PROGRAM_VER " -- Copyright (C) 1992-96 Tormod Tjaberg & Hans Peter Verne",
  91.   "",
  92.   "Usage: gsar [options] [infile(s)] [outfile]",
  93.   "Options are:",
  94.   "-s<string> Search string ",
  95.   "-r[string] Replace string. Use '-r' to delete the search string from the file",
  96.   "-i         Ignore case difference when comparing strings",
  97.   "-B         just display search & replace Buffers",
  98.   "-f         Force overwrite of an existing output file",
  99.   "-o         Overwrite the existing input file",
  100.   "-c[n]      show textual Context of match, 'n' is number of bytes in context",
  101.   "-x[n]      show context as a heX dump, 'n' is number of bytes in context",
  102.   "-b         display Byte offsets of matches in file",
  103.   "-l         only List filespec and number of matches (default)",
  104.   "-h         suppress display of filespec when displaying context or offsets",
  105.   "-du        convert a DOS ASCII file to UNIX (strips carriage return)",
  106.   "-ud        convert a UNIX ASCII file to DOS (adds carriage return)",
  107.   "-F         'Filter' mode, input from stdin and eventual output to stdout",
  108.   "-G         display the GNU General Public Licence",
  109.   "",
  110.   "Ctrl characters may be entered by using a ':' in the string followed by the",
  111.   "ASCII value of the character. The value is entered using ':' followed by three",
  112.   "decimal digits or ':x' followed by two hex numbers. To enter ':' use '::'",
  113.   NULL
  114. };
  115.  
  116. char *Licence[] =
  117. {
  118.   "This program is free software; you can redistribute it and/or modify",
  119.   "it under the terms of the GNU General Public License as published by",
  120.   "the Free Software Foundation; either version 2 of the License, or",
  121.   "(at your option) any later version.",
  122.   "",
  123.   "This program is distributed in the hope that it will be useful,",
  124.   "but WITHOUT ANY WARRANTY; without even the implied warranty of",
  125.   "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the",
  126.   "GNU General Public License for more details.",
  127.   "",
  128.   "You should have received a copy of the GNU General Public License",
  129.   "along with this program; if not, write to the Free Software",
  130.   "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.",
  131.   NULL
  132. };
  133.  
  134.  
  135. /* Display the GNU General Public License
  136.  */
  137. void ShowLicence(void)
  138. {
  139.    int i = 0;
  140.  
  141.    while (Licence[i] != NULL)
  142.    {
  143.       fputs(Licence[i++], Ctrl.fpMsg);
  144.       fputc('\n', Ctrl.fpMsg);
  145.    }
  146. }
  147.  
  148.  
  149. /* Input  : Message to be displayed with the format of standard printf
  150.  * Returns: Nothing, but instead it exits to operating system
  151.  *
  152.  * Terminate program, return to OS with a suitable return value
  153.  * exit() will close all open files. All fatal errors are written
  154.  * to stderr.
  155.  */
  156. void Abort(char *pMessage, ...)
  157. {
  158.    va_list argp;
  159.  
  160.    fprintf(stderr, "gsar: ");
  161.    va_start(argp, pMessage);
  162.    vfprintf(stderr, pMessage, argp);
  163.    va_end(argp);
  164.    fprintf(stderr, "\n");
  165.    exit(EXIT_FAILURE);  /* exit & tell operating system that we've failed */
  166. }
  167.  
  168.  
  169. /* Ctrl-Break handler. Returns to operating system
  170.  */
  171. void CtrlBreak(int Val)
  172. {
  173.    if (fCriticalPart)
  174.       return;
  175.  
  176.    signal(SIGINT, SIG_IGN);
  177.  
  178.    /* Before we die try to clean up as much as possible
  179.     * make sure we don't delete stdout...
  180.     */
  181.    if (fSearchReplace && pOutFile != NULL && !fFilter)
  182.       remove(pOutFile);
  183.  
  184.    exit(EXIT_FAILURE);  /* exit & tell operating system that we've failed */
  185. }
  186.  
  187.  
  188. /* Input  : pActStr - pointer to actual string which is to be duplicated
  189.  * Returns: pDupStr - pointer to malloc'd duplicate
  190.  *          NULL - Out of memory
  191.  *
  192.  * Duplicates a string by malloc'ing and then doing a strcpy
  193.  */
  194. char *DupStr(char *pActStr)
  195. {
  196.    register char *pDupStr;
  197.  
  198.    pDupStr = (char *) malloc(strlen(pActStr) + 1);
  199.    if (pDupStr)
  200.       strcpy(pDupStr, pActStr);
  201.    return pDupStr;
  202. }
  203.  
  204.  
  205. /* Input  : filespec - a filespec which contains a path and a filename
  206.  * Returns: savfilespec - pointer to malloc'd string with path
  207.  *
  208.  * Extracts the path from a filespec
  209.  */
  210. char *ExtractPathFromFSpec(register char *filespec)
  211. {
  212.    register char *p;
  213.    register char *savfilespec;
  214.  
  215.    savfilespec = DupStr(filespec); /* avoid destroying the original */
  216.  
  217.    /* Start at end of string and back up till we find the beginning */
  218.    /* of the filename or a path.               */
  219.    for (p = savfilespec + strlen(savfilespec);
  220.         p != savfilespec && !IS_PATH_DELIM(*(p - 1));
  221.         p--)
  222.       ;
  223.    *p = '\0';
  224.    return savfilespec;
  225. }
  226.  
  227.  
  228. /* Input  : pPath - which has to be properly terminated
  229.  *          pPrefix - tmp filename prefix maximum 4 chars
  230.  * Returns: pointer to static buffer
  231.  *          NULL - unable to generate tmp file name
  232.  *
  233.  * Generates a temporary filename by combining an optional path,
  234.  * a prefix ,a number between 0 & SHRT_MAX and the suffix '.tmp'.
  235.  */
  236. char *TmpName(char *pPath, char *pPrefix)
  237. {
  238.    static char FileSpec[FILENAME_MAX ];
  239.    static char Seed = 0;
  240.  
  241.    static short TmpNum;
  242.    char *pDigits;
  243.    unsigned short i;
  244.    struct stat buf;
  245.  
  246.    *FileSpec = '\0'; /* Null terminate the buffer so strcat will always work */
  247.    if (!Seed)      /* if first time through */
  248.    {
  249.       Seed++;
  250.       TmpNum = -1; /* since we increment this will make the first number 0000 */
  251.    }
  252.  
  253.    if (pPath != NULL)
  254.       strcpy(FileSpec, pPath);     /* first the path  */
  255.    if (pPrefix != NULL)
  256.       strcat(FileSpec, pPrefix);   /* then the prefix */
  257.  
  258.    /* pointer to start of digits in filespec */
  259.    pDigits = FileSpec + strlen(FileSpec);
  260.  
  261.    for (i = 0; i <= SHRT_MAX; i++)     /* try SHRT_MAX times */
  262.    {
  263.       TmpNum++;                        /* TmpNum is static ! */
  264.       sprintf(pDigits, "%04x", TmpNum)